using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Interfaces;
using UniversalAdmin.Domain.Repositories;

namespace UniversalAdmin.Application.Services;

public interface IArticleCategoryService
{
  Task<List<ArticleCategoryDto>> GetAllActiveAsync();
  Task<ArticleCategoryDto?> GetByIdAsync(int id);
  Task<ArticleCategoryDto> CreateAsync(CreateArticleCategoryDto dto);
  Task<ArticleCategoryDto> UpdateAsync(int id, UpdateArticleCategoryDto dto);
  Task DeleteAsync(int id);
  Task<List<ArticleCategoryTreeDto>> GetTreeAsync();
}

public class ArticleCategoryService : IArticleCategoryService
{
  private readonly IUnitOfWork _uow;
  private readonly IArticleCategoryRepository _repo;

  public ArticleCategoryService(IUnitOfWork uow, IArticleCategoryRepository repo)
  {
    _uow = uow;
    _repo = repo;
  }

  public async Task<List<ArticleCategoryDto>> GetAllActiveAsync()
  {
    var categories = await _repo.GetAllActiveAsync();
    return categories.Select(MapToDto).ToList();
  }

  public async Task<ArticleCategoryDto?> GetByIdAsync(int id)
  {
    var category = await _repo.GetByIdAsync(id);
    return category == null ? null : MapToDto(category);
  }

  public async Task<ArticleCategoryDto> CreateAsync(CreateArticleCategoryDto dto)
  {
    var category = ArticleCategory.Create(
        dto.Name,
        dto.Description,
        dto.ParentId,
        dto.Sort,
        dto.IsActive
    );

    await _repo.AddAsync(category);
    await _uow.SaveChangesAsync();
    return MapToDto(category);
  }

  public async Task<ArticleCategoryDto> UpdateAsync(int id, UpdateArticleCategoryDto dto)
  {
    var category = await _repo.GetByIdAsync(id)
        ?? throw new KeyNotFoundException("分类不存在");

    category.Update(
        dto.Name,
        dto.Description,
        dto.ParentId,
        dto.Sort,
        dto.IsActive
    );

    await _repo.UpdateAsync(category);
    await _uow.SaveChangesAsync();
    return MapToDto(category);
  }

  public async Task DeleteAsync(int id)
  {
    var category = await _repo.GetByIdAsync(id)
        ?? throw new KeyNotFoundException("分类不存在");

    // 检查是否有子分类
    var hasChildren = await _repo.AnyAsync(c => c.ParentId == id);
    if (hasChildren)
      throw new InvalidOperationException("该分类下存在子分类，无法删除");

    // 检查是否有文章引用
    var hasArticles = await _uow.Articles.AnyAsync(a => a.CategoryId == id);
    if (hasArticles)
      throw new InvalidOperationException("该分类下存在文章，无法删除");

    await _repo.RemoveAsync(category);
    await _uow.SaveChangesAsync();
  }

  /// <summary>
  /// 获取分类树（支持多级）
  /// </summary>
  public async Task<List<ArticleCategoryTreeDto>> GetTreeAsync()
  {
    var all = await _repo.GetAllAsync();
    var rootItems = all.Where(c => c.ParentId == null).OrderBy(c => c.Sort);
    return BuildTree(rootItems, all).ToList();
  }

  private IEnumerable<ArticleCategoryTreeDto> BuildTree(
      IEnumerable<ArticleCategory> categories,
      IEnumerable<ArticleCategory> all)
  {
    foreach (var item in categories)
    {
      yield return new ArticleCategoryTreeDto
      {
        Id = item.Id,
        Name = item.Name,
        Description = item.Description,
        ParentId = item.ParentId,
        Sort = item.Sort,
        IsActive = item.IsActive,
        Children = BuildTree(all.Where(c => c.ParentId == item.Id), all).ToList()
      };
    }
  }

  private static ArticleCategoryDto MapToDto(ArticleCategory c) => new()
  {
    Id = c.Id,
    Name = c.Name,
    Description = c.Description,
    ParentId = c.ParentId,
    Sort = c.Sort,
    IsActive = c.IsActive,
    CreatedAt = c.CreatedAt,
    UpdatedAt = c.UpdatedAt
  };
}